
package com.hlkj.pay.util;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

import org.springframework.util.StringUtils;

import com.hlkj.framework.common.util.collection.CollectionUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;

import cn.hutool.core.lang.WeightRandom;
import cn.hutool.core.util.RandomUtil;
import net.dreamlu.mica.core.utils.StringPool;

/**
 * @author HlpayTeam
 * @date 2024/10/10 11:34
 */
public class MerchantAppChannelRouterUtil {

    public static ConcurrentMap<String, double[]> arrMap = new ConcurrentHashMap<String, double[]>();


    public static MerchantAccessAuthDO routerAt(List<MerchantAccessAuthDO> merchantAccessAuthList) {
        if (CollectionUtils.isEmpty(merchantAccessAuthList)) {
            return null;
        }
        if (merchantAccessAuthList.size() == 1) {
            return merchantAccessAuthList.get(0);
        }

        // 转权重集合
        List<WeightRandom.WeightObj<String>> list = new ArrayList<>();
        for(MerchantAccessAuthDO merchantAccessAuthDO:merchantAccessAuthList){
            list.add(new WeightRandom.WeightObj<>(merchantAccessAuthDO.getId().toString(), merchantAccessAuthDO.getWeight()==null?0:merchantAccessAuthDO.getWeight()));
        }
        //创建带有权重的随机生成器
        WeightRandom wr = RandomUtil.weightRandom(list);
        // 本次随机获取的渠道ID
        String channelId = wr.next().toString();

        for(MerchantAccessAuthDO merchantAccessAuthDO:merchantAccessAuthList){
            if(merchantAccessAuthDO.getId().toString().equals(channelId)){
                return merchantAccessAuthDO;
            }
        }
        return merchantAccessAuthList.get(0);
    }

    /**
     * 渠道随机
     * @param merchantAppChannelList
     * @return
     */
    public static MerchantAppChannelDO routerChannel(List<MerchantAppChannelDO> merchantAppChannelList) {
        if (CollectionUtils.isEmpty(merchantAppChannelList)) {
            return null;
        }
        if (merchantAppChannelList.size() == 1) {
            return merchantAppChannelList.get(0);
        }
        // 转权重集合
        List<WeightRandom.WeightObj<String>> list = new ArrayList<>();
        for(MerchantAppChannelDO merchantAppChannelDO:merchantAppChannelList){
            list.add(new WeightRandom.WeightObj<>(merchantAppChannelDO.getId().toString(), merchantAppChannelDO.getWeight()==null?0:merchantAppChannelDO.getWeight()));
        }
        //创建带有权重的随机生成器
        WeightRandom wr = RandomUtil.weightRandom(list);
        // 本次随机获取的渠道ID
        String channelId = wr.next().toString();

        for(MerchantAppChannelDO merchantAppChannelDO:merchantAppChannelList){
            if(merchantAppChannelDO.getId().toString().equals(channelId)){
                return merchantAppChannelDO;
            }
        }
        return merchantAppChannelList.get(0);
    }

    public static MerchantAppChannelDO router(List<MerchantAppChannelDO> merchantAppChannelList) {
        if (CollectionUtils.isEmpty(merchantAppChannelList)) {
            return null;
        }
        if (merchantAppChannelList.size() == 1) {
            return merchantAppChannelList.get(0);
        }
        List<Integer> weightList = merchantAppChannelList.stream().map(merchantAppChannelDO -> merchantAppChannelDO.getWeight()).collect(Collectors.toList());

        String key = StringUtils.collectionToDelimitedString(weightList, StringPool.DASH);
        double[] arr = null;
        if (arrMap.containsKey(key)) {
            arr = arrMap.get(key);
        }
        else {
            // 总权重
            double weight = merchantAppChannelList.stream().mapToDouble(merchantAppChannelDO -> merchantAppChannelDO.getWeight()).sum();
            // 接下来就是要将每个人的权重占比给算出来：个人权重 ÷ 总权重 = 每个人的权重占比
            // 2.计算权重的总和

            // 3.计算每一个人的实际占比存起来，这里可以用数组也可以用集合
            // [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
            arr = new double[merchantAppChannelList.size()];
            int index = 0;
            for (MerchantAppChannelDO merchantAppChannelDO : merchantAppChannelList) {
                arr[index] = merchantAppChannelDO.getWeight() / weight;
                // BigDecimal bd = new BigDecimal(merchantAppChannelDO.getWeight() / weight);
                // arr[index]=bd.intValue();
                index++;
            }
            // 4.计算每一个人的权重占比范围
            // 第一个人的范围是0 ~ 0.1，第二个人的范围是0.1~0.2，我们需要想清楚0.2是怎么来的，是不是前一个人0.1的基础上，再去加上自己本身？
            // 第三个人的范围也是在前一个人的基础上（0.2）加上自己本身的范围0.1，就变成了0.3
            for (int i = 1; i < arr.length; i++) {
                arr[i] = arr[i] + arr[i - 1];
            }
            System.out.println(JsonUtils.toJsonString(arr));
        }
        // 此时如果直接打印arr，有些小数是不精确的，但是这个不精确对结果影响的不是很大，是在我们能接受范围之内的。
        // 5.随机抽取
        // 获取一个0.0~1.0之间的随机数
        double number = Math.random();
        // System.out.println(number);
        // 判断number在arr中的位置
        // 由于在arr中数据是升序排列的，因此可以使用二分查找法
        // 方法回返回： - 插入点 - 1
        // 插入点 = -方法回返回 - 1
        // 获取number这个数据在数组当中的插入点位置
        int result = -Arrays.binarySearch(arr, number) - 1;
        // 获取到插入点的位置后，我们就知道是哪个学生了
        return merchantAppChannelList.get(result);
    }

    public static void main(String[] args) {
        List<WeightRandom.WeightObj<String>> list = new ArrayList<>();
        list.add(new WeightRandom.WeightObj<>("A", 7));
        list.add(new WeightRandom.WeightObj<>("B", 8));
        // list.add(new WeightRandom.WeightObj<>("C", 0));
        // list.add(new WeightRandom.WeightObj<>("D", 0));
        // list.add(new WeightRandom.WeightObj<>("E", 0));
        // list.add(new WeightRandom.WeightObj<>("F", 0));
        // list.add(new WeightRandom.WeightObj<>("G", 0));
        // list.add(new WeightRandom.WeightObj<>("H", 0));
        // list.add(new WeightRandom.WeightObj<>("J", 0));

        //创建带有权重的随机生成器
        WeightRandom wr = RandomUtil.weightRandom(list);
        for(int i=0;i<10;i++){
            System.out.println(wr.next().toString());
        }


    }
}
